Desktop.Window = function (parent, windowIconPath, windowName) {
    var elementReference = undefined; // Set by renderApplicationWindow.
    var _windowIconPath = windowIconPath;
    var _windowName = windowName;
    this.setElementReference = function (reference) {
        elementReference = reference;
    }

    this.getElementReference = function () {
        return elementReference;
    }

    this.getWindowIconPath = function () {
        return _windowIconPath;
    }

    this.getWindowName = function () {
        return _windowName;
    }
    this.renderWindow(parent);
}

/*
Used to make sure that inparameters for subclasses are not undefined
when we set the subclass prototype to the constructor function of the
baseclass.
*/
Desktop.Window.subclassOf = function (base) {
    Desktop.Window._subclassOf.prototype = base.prototype;
    return new Desktop.Window._subclassOf();
}
Desktop.Window._subclassOf = function () { };

Desktop.Window.prototype.renderWindow = function (parent) {
    // Get the requierd elements.
    var desktop = $('#desktopContainer');
    var taskBar = $(document).find('#taskBarVisual');

    // Create the window.
    var window = document.createElement('div');
    window.className = 'window';

    // Save a reference to the window.
    this.setElementReference(window);

    this.createWindowStructure();

    // Add it to the DOM-structure.
    parent.appendChild(window);

    // Get the number of already open windows.
    var numberOfWindows = Desktop.getNumberOfOpenedWindows();
    var xOffset = Desktop.getWindowXOffset();

    /* 
    Check if we need to offset to not go outside the screen.
    We have to make a difference between the first column of
    open windows and the rest since the offset starts at one
    so that our modulus works correctly.
    */
    if (xOffset > 1) {
        if (numberOfWindows % 21 == 0) {
            Desktop.increaseWindowXOffset();
            Desktop.resetOpenedWindows();
        }
    }
    else {
        if (numberOfWindows % 20 == 0) {
            Desktop.increaseWindowXOffset();
            Desktop.resetOpenedWindows();
        }
    }

    // Check if we moved the windows so much to the right that they wouldn't fit on the screen.
    if (numberOfWindows == 21) {
        if (xOffset % 4 == 0) {
            Desktop.resetWindowXOffset();
        }
    }

    /* 
    Add some predetermind number of pixels to the windows 
    position depending on how much we offset the window
    already.

    We are making a difference between offset of less 
    than 2 and the rest due to the same reason as above 
    (starts at 1 not 0);
    */
    if (xOffset < 2) {
        $(window).css('left', $(window).position().left + (250 * (xOffset - 1)) + (10 * numberOfWindows));
        $(window).css('top', $(window).position().top + (20 * numberOfWindows));
    }
    else {
        $(window).css('left', $(window).position().left + (250 * (xOffset - 1)) + (10 * numberOfWindows));
        $(window).css('top', $(window).position().top + (20 * (numberOfWindows - 1)));
    }

    var windowTop = parseInt($(window).css('top'));
    var windowHeight = parseInt($(window).css('height'));
    var desktopBottom = parseInt($(desktop).css('height'));
    var windowBottom = windowTop + windowHeight;
    var taskBarHeight = parseInt($(taskBar).css('height'));
    var adjustedDesktopBottom = desktopBottom - taskBarHeight;

    // Get the content.
    var contentContainer = $(window).find('.windowContentContainer');

    // Check the height of the window.
    if (windowBottom >= adjustedDesktopBottom) {
        // Get the height difference between the window and the desktops bottom.
        var heightDiff = windowBottom - adjustedDesktopBottom;
        // If the heightDifference is less than zero add the taskbars height as the difference.
        if (heightDiff <= 0) {
            heightDiff = taskBarHeight;
        }

        // Calculate the new height.
        var newHeight = windowHeight - (heightDiff + taskBarHeight);

        // Get the middle element to set the new height.
        var middle = $(window).find('.windowMiddle');
        $(middle).css('height', newHeight);

        // Since we get an overflow add a scrollbar.
        $(contentContainer).addClass('scrollable');
    }

    var windowLeft = parseInt($(window).css('left'));
    var windowWidth = parseInt($(window).css('width'));
    var windowRight = windowLeft + windowWidth;
    var desktopWidth = parseInt($(desktop).css('width'));

    var extraMargin = 20;
    // Check the width of the window.
    if (windowRight >= (desktopWidth - 5)) {
        // Get the difference between the right side and what would be outside the desktop
        // to determin how much we need to reduce the width.
        var widthDiff = windowRight - desktopWidth;

        var newWidth = windowWidth - widthDiff;
        newWidth -= extraMargin;

        // Get the elements that we need to give a new width.
        var topBar = $(window).find('.topBar')[0];
        var bottomBar = $(window).find('.bottomBar')[0];

        // Set the new width.
        $(contentContainer).css('width', newWidth);
        $(topBar).css('width', newWidth + 10);
        $(bottomBar).css('width', newWidth + 10);

        // Since we get an overflow add a scrollbar.
        $(contentContainer).addClass('scrollable');
    }

    var that = this;
    // Lastly add the event for when we mousebutton down on a window.
    $(window).mousedown(function () { that.onMousedownEvent(window); false; });
}

Desktop.Window.prototype.createWindowStructure = function () {
    // Get the reference to the window.
    var windowReference = this.getElementReference();

    // Create the structure to put in the window.
    var structureToAppend = '<div class="windowTop">' +
                                '<div class="topBar">' +
                                    '<div class="topContent"></div>' +
                                    '<div class="close"></div>' +
                                '</div>' +
                                '<div class="topRightCorner"></div>' +
                            '</div>' +
                            '<div class="windowMiddle">' +
                                '<div class="windowLeft"></div>' +
                                '<div class="windowContentContainer"></div>' +
                                '<div class="windowRight"></div>' +
                            '</div>' +
                            '<div class="windowBottom">' +
                                '<div class="bottomBar"></div>' +
                            '</div>';

    // Add the structure to the window.
    $(windowReference).append(structureToAppend);

    // Add the content to the topBar
    var topBar = $(windowReference).find('.topContent')[0];
    this.createTopBarContent(topBar);

    // Add the content to the bottomBar
    var bottomBar = $(windowReference).find('.bottomBar')[0];
    this.createBottomBarContent(bottomBar);

    // Add the content that is the actual application.
    this.createWindowContent(windowReference);

    // Create the event so users are able to close an open window.
    this.createCloseEvent($(windowReference).find('.close')[0], this.getElementReference());
}

Desktop.Window.prototype.createCloseEvent = function (closeElement, reference) {
    var that = this;
    $(closeElement).click(function () { that.closeEvent(reference) });
}

Desktop.Window.prototype.closeEvent = function (reference) {
    // Remove the element from the DOM-structure.
    var elementReference = this.getElementReference();
    elementReference.parentNode.removeChild(elementReference);
}

Desktop.Window.prototype.createTopBarContent = function (topBar) {
    // Create the icon for the window.
    var icon = document.createElement('img');
    icon.className = 'windowIcon';
    icon.src = this.getWindowIconPath();

    // Create the name for the window.
    var appNameDiv = document.createElement('div');
    appNameDiv.className = 'windowName';
    appNameDiv.textContent = this.getWindowName();

    // Add them to the open window.
    topBar.appendChild(icon);
    topBar.appendChild(appNameDiv);
}

Desktop.Window.prototype.onMousedownEvent = function (window) {
    // Get the parent of the window.
    var parent = window.parentNode;

    /*
    Check through all the windows in the parent and run 
    removeClass incase any of the windows are already focused.
    */
    var collectionOfWindows = $(parent).find('.window');
    for (var i = 0; i < collectionOfWindows.length; i++) {
        $(collectionOfWindows[i]).removeClass('windowFocus');
    }

    // Focus the clicked window.
    $(window).addClass('windowFocus');
}

// Override in child-class to add whatever should go inside the window.
Desktop.Window.prototype.createWindowContent = function (_windowReference) { }

// Override in child-class to add whatever should go inside bottom-bar of the window.
Desktop.Window.prototype.createBottomBarContent = function (bottomBar) { }